package de.axone.wash.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import de.axone.wash.DefaultWash;
import de.axone.wash.Wash;
import de.axone.wash.Wash.WashException;


public class WashClient {
	
	public static enum Method { GET, POST; }
	
	public class ClientException extends Exception {
		
		public ClientException( String message ) { super( message ); }
		public ClientException( String message, Throwable cause ) { super( message, cause ); }
		public ClientException( Throwable cause ) { super( cause ); }
	}
	
	private URL url;
	
	public WashClient( URL url ) {
		
		setUrl( url );
	}
	
	public URL getUrl() {
	
		return url;
	}
	
	public void setUrl( URL url ) {
	
		this.url = url;
	}

	public Wash call( Wash request ) throws ClientException, WashException {
		
		return call( null, null, request, Method.POST );
	}
	
	public Wash call( String service, String operation, Wash request )
	throws ClientException, WashException {
		
		return call( service, operation, request, Method.POST );
	}
	
	public Wash call( String service, String operation, Wash request, Method method ) 
	throws ClientException, WashException {
		
		// Build payload query
		String payload = request.serialize();
		String data=null;
		try {
			data = "wash.q=" + URLEncoder.encode( payload, "utf-8" );
			if( service != null ) data += "&wash.service=\"" + URLEncoder.encode( service, "utf-8" );
			if( operation != null ) data += "&wash.op=\"" + URLEncoder.encode( operation, "utf-8" );
			
		} catch( UnsupportedEncodingException e ) {
			e.printStackTrace();
		}
		
		URLConnection connection;
		try {
			connection = url.openConnection();
			connection.setDoOutput( true );
			
			OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream() );
			
			out.write( data );
			out.flush();
			
		} catch( IOException e ) {
			throw new ClientException( "Connection error sending", e );
		}
		
		String buffer = null;
		try {
			buffer = slurp( connection.getInputStream() );
			
		} catch( IOException e ) {
			throw new ClientException( "Connection error receiving", e );
		}
		
		Wash result = new DefaultWash();
		
		result.deserialize( buffer.toString() );
		
		return result;
	}
	
	
	public static String slurp( InputStream in )throws IOException {
		
	    StringBuilder out = new StringBuilder();
	    
	    byte[] b = new byte[1518]; //Ethernet default MTU
	    
	    for (int n; (n = in.read(b)) != -1;) {
	        out.append(new String(b, 0, n));
	    }
	    return out.toString();
	}
}
